#pragma once

#include <vector>
#include <string>
#include <iostream>
#include <thread>
#include <mutex>
#include <mariadb/mysql.h>

namespace ns_sql
{
    class MySQLManager {
    private:
        MYSQL *conn;
        std::string errorMessage;
        std::mutex _mutex;

    public:
        MySQLManager() : conn(nullptr) {}

        ~MySQLManager() {
            closeDatabase();
        }

        bool openDatabase(const std::string &host, const std::string &user, const std::string &password, const std::string &dbname) {
            std::unique_lock<std::mutex> lock(_mutex); 
            conn = mysql_init(nullptr);
            if (!conn) {
                errorMessage = "MySQL initialization failed";
                return false;
            }

            if (!mysql_real_connect(conn, host.c_str(), user.c_str(), password.c_str(), dbname.c_str(), 0, nullptr, 0)) {
                errorMessage = mysql_error(conn);
                return false;
            }
            return true;
        }

        void closeDatabase() {
            std::unique_lock<std::mutex> lock(_mutex); 
            if (conn) {
                mysql_close(conn);
                conn = nullptr;
            }
        }

        std::string getErrorMessage() const {
            return errorMessage;
        }

        bool executeQuery(const std::string &query) {
            std::unique_lock<std::mutex> lock(_mutex); 
            if (mysql_query(conn, query.c_str())) {
                errorMessage = mysql_error(conn);
                return false;
            }
            return true;
        }

        // 执行SELECT查询并返回结果集
        std::vector<std::vector<std::string>> executeSelect(const std::string &query) {
            std::unique_lock<std::mutex> lock(_mutex); 
            std::vector<std::vector<std::string>> results;
            if (mysql_query(conn, query.c_str())) {
                errorMessage = mysql_error(conn);
                return results;
            }

            MYSQL_RES *res = mysql_store_result(conn);
            if (!res) {
                errorMessage = mysql_error(conn);
                return results;
            }

            MYSQL_ROW row;
            while ((row = mysql_fetch_row(res))) {
                std::vector<std::string> rowData;
                for (unsigned int i = 0; i < mysql_num_fields(res); ++i) {
                    rowData.push_back(row[i] ? row[i] : "NULL");
                }
                results.push_back(rowData);
            }
            mysql_free_result(res);
            return results;
        }

        // 封装结果集
        class MySQLResult {
        private:
            MYSQL_RES *res;
            MYSQL_ROW row;
            unsigned int num_fields;

        public:
            MySQLResult(MYSQL_RES *result) : res(result), row(nullptr), num_fields(mysql_num_fields(res)) {}

            ~MySQLResult() {
                if (res) {
                    mysql_free_result(res);
                }
            }

            // 返回下一行数据
            bool next() {
                row = mysql_fetch_row(res);
                return row != nullptr;
            }

            // 获取当前行的列值
            std::string getString(unsigned int index) const {
                return (row && row[index]) ? row[index] : "NULL";
            }

            unsigned int getNumFields() const {
                return num_fields;
            }

            int getInt(unsigned int index) const {
                if (!row || !row[index] || std::string(row[index]) == "NULL") {
                    return 0;  // 默认值为0
                }
                try {
                    return std::stoi(row[index]);
                } catch (const std::exception &e) {
                    return 0;  // 如果转换失败，返回默认值0
                }
            }

            int getDouble(unsigned int index) const {
                if (!row || !row[index] || std::string(row[index]) == "NULL") {
                    return 0.0;  // 默认值为0.0
                }
                try {
                    return std::stod(row[index]);
                } catch (const std::exception &e) {
                    return 0.0;  // 如果转换失败，返回默认值0.0
                }
            }
        };

        // getResult方法，返回一个封装了查询结果的MySQLResult对象
        MySQLResult getResult(const std::string &query) {
            if (mysql_query(conn, query.c_str())) {
                errorMessage = mysql_error(conn);
                return MySQLResult(nullptr);
            }

            MYSQL_RES *res = mysql_store_result(conn);
            if (!res) {
                errorMessage = mysql_error(conn);
                return MySQLResult(nullptr);
            }

            return MySQLResult(res);
        }
    };

}
